package org.finesys.gateway.configure;

import java.util.Set;
import java.util.stream.Collectors;

import org.springdoc.core.AbstractSwaggerUiConfigProperties;
import org.springdoc.core.SwaggerUiConfigProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Configuration;

import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.common.utils.StringUtils;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "springdoc.api-docs.enabled", matchIfMissing = true)
public class SpringDocConfiguration implements InitializingBean {

    public static final String API_URI = "/%s/v3/api-docs";
    private final SwaggerUiConfigProperties swaggerUiConfigProperties;
    private final DiscoveryClient discoveryClient;

    @Override
    public void afterPropertiesSet() throws Exception {
        /**
         * 在初始化后调用的方法，用于注册 SwaggerDocRegister 订阅器
         */
        NotifyCenter.registerSubscriber(new SwaggerDocRegister(swaggerUiConfigProperties, discoveryClient));
    }
}

/**
 * 获取nacos中的注册服务
 */
@RequiredArgsConstructor
class SwaggerDocRegister extends Subscriber<InstancesChangeEvent> {
    private final SwaggerUiConfigProperties swaggerUiConfigProperties;
    private final DiscoveryClient discoveryClient;

    @Override
    public void onEvent(InstancesChangeEvent instancesChangeEvent) {
        Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> swaggerUrlSet = discoveryClient.getServices()
                .stream()
                .flatMap(serviceId -> discoveryClient.getInstances(serviceId).stream())
                .filter(instance -> StringUtils.isNotBlank(instance.getMetadata().get("spring-doc")))
                .map(instance -> {
                    AbstractSwaggerUiConfigProperties.SwaggerUrl swaggerUrl = new AbstractSwaggerUiConfigProperties.SwaggerUrl();
                    swaggerUrl.setName(instance.getServiceId());
                    swaggerUrl.setUrl(String.format(SpringDocConfiguration.API_URI, instance.getMetadata().get("spring-doc")));
                    return swaggerUrl;
                })
                .collect(Collectors.toSet());

        swaggerUiConfigProperties.setUrls(swaggerUrlSet);
    }

    @Override
    public Class<? extends Event> subscribeType() {
        return InstancesChangeEvent.class;
    }
}

